<template><div><h2 id="任务调度" tabindex="-1"><a class="header-anchor" href="#任务调度"><span>任务调度</span></a></h2>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#defining-schedules">定义调度</a>
<ul>
<li><a href="#scheduling-artisan-commands">Artisan 命令调度</a></li>
<li><a href="#scheduling-queued-jobs">队列任务调度</a></li>
<li><a href="#scheduling-shell-commands">Shell 命令调度</a></li>
<li><a href="#schedule-frequency-options">调度频率设置</a></li>
<li><a href="#timezones">时区</a></li>
<li><a href="#preventing-task-overlaps">避免任务重复</a></li>
<li><a href="#running-tasks-on-one-server">单机任务调度</a></li>
<li><a href="#background-tasks">后台任务</a></li>
<li><a href="#maintenance-mode">维护模式</a></li>
</ul>
</li>
<li><a href="#running-the-scheduler">运行调度程序</a>
<ul>
<li><a href="#running-the-scheduler-locally">本地运行调度程序</a></li>
</ul>
</li>
<li><a href="#task-output">任务输出</a></li>
<li><a href="#task-hooks">任务钩子</a></li>
<li><a href="#events">事件</a></li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>过去，你可能需要在服务器上为每一个调度任务去创建 Cron 条目。因为这些任务的调度不是通过代码控制的，你要查看或新增任务调度都需要通过 SSH 远程登录到服务器上去操作，所以这种方式很快会让人变得痛苦不堪。</p>
<p>Laravel 的命令行调度器允许你在 Laravel 中清晰明了地定义命令调度。在使用这个任务调度器时，你只需要在你的服务器上创建单个 Cron 入口。你的任务调度在 <code v-pre>app/Console/Kernel.php</code> 的 <code v-pre>schedule</code> 方法中进行定义。为了帮助你更好的入门，这个方法中有个简单的例子。</p>
<h2 id="定义调度" tabindex="-1"><a class="header-anchor" href="#定义调度"><span>定义调度</span></a></h2>
<p>你可以在 <code v-pre>App\Console\Kernel</code> 类的 <code v-pre>schedule</code> 方法中定义所有的调度任务。在开始之前，我们来看一个例子：我们计划每天午夜执行一个闭包，这个闭包会执行一次数据库语句去清空一张表：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Console</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Console<span class="token punctuation">\</span>Scheduling<span class="token punctuation">\</span>Schedule</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Console<span class="token punctuation">\</span>Kernel</span> <span class="token keyword">as</span> ConsoleKernel<span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>DB</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">Kernel</span> <span class="token keyword">extends</span> <span class="token class-name">ConsoleKernel</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 定义应用中的命令调度</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">schedule</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Schedule</span> <span class="token variable">$schedule</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token class-name static-context">DB</span><span class="token operator">::</span><span class="token function">table</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'recent_users'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>除了调用闭包这种方式来调度外，你还可以调用 <a href="https://secure.php.net/manual/en/language.oop5.magic.php#object.invoke" target="_blank" rel="noopener noreferrer">可调用对象</a>。 可调用对象是简单的 PHP 类，包含一个 <code v-pre>__invoke</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">DeleteRecentUsers</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你想查看任务计划的概述及其下次计划运行时间，你可以使用 <code v-pre>schedule:list</code> Artisan 命令：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan schedule:list</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="artisan-命令调度" tabindex="-1"><a class="header-anchor" href="#artisan-命令调度"><span>Artisan 命令调度</span></a></h3>
<p>调度方式不仅有调用闭包，还有调用 <a href="https://learnku.com/docs/laravel/10.x/artisan" target="_blank" rel="noopener noreferrer">Artisan commands</a> 和操作系统命令。例如，你可以给 command 方法传递命令名称或类来调度一个 <code v-pre>Artisan</code> 命令：</p>
<p>当使用命令类名调度 <code v-pre>Artisan</code> 命令时，你可以通过一个数组传递附加的命令行参数，且这些参数需要在命令触发时提供：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Console<span class="token punctuation">\</span>Commands<span class="token punctuation">\</span>SendEmailsCommand</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send Taylor --force'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token class-name static-context">SendEmailsCommand</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'Taylor'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'--force'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="队列任务调度" tabindex="-1"><a class="header-anchor" href="#队列任务调度"><span>队列任务调度</span></a></h3>
<p><code v-pre>job</code> 方法可以用来调度 <a href="https://learnku.com/docs/laravel/10.x/queues" target="_blank" rel="noopener noreferrer">queued job</a>。此方法提供了一种快捷方式来调度任务，而无需使用 <code v-pre>call</code> 方法创建闭包来调度任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Jobs<span class="token punctuation">\</span>Heartbeat</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">job</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Heartbeat</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">everyFiveMinutes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>job</code> 方法提供了可选的第二，三参数，分别指定任务将被放置的队列名称及连接：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Jobs<span class="token punctuation">\</span>Heartbeat</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 分发任务到「heartbeats」队列及「sqs」连接...</span></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">job</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Heartbeat</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'heartbeats'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'sqs'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">everyFiveMinutes</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="shell-命令调度" tabindex="-1"><a class="header-anchor" href="#shell-命令调度"><span>Shell 命令调度</span></a></h3>
<p><code v-pre>exec</code> 方法可发送命令到操作系统：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">exec</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'node /home/forge/script.js'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="调度频率选项" tabindex="-1"><a class="header-anchor" href="#调度频率选项"><span>调度频率选项</span></a></h3>
<p>我们已经看到了几个如何设置任务在指定时间间隔运行的例子。不仅如此，你还有更多的任务调度频率可选：</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>-&gt;cron('* * * * *');</code></td>
<td>按自定义 cron 计划运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everySecond();</code></td>
<td>每秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTwoSeconds();</code></td>
<td>每两秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFiveSeconds();</code></td>
<td>每五秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTenSeconds();</code></td>
<td>每十秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFifteenSeconds();</code></td>
<td>每 15 秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTwentySeconds();</code></td>
<td>每 20 秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyThirtySeconds();</code></td>
<td>每 30 秒运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyMinute();</code></td>
<td>每分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTwoMinutes();</code></td>
<td>每两分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyThreeMinutes();</code></td>
<td>每三分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFourMinutes();</code></td>
<td>每四分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFiveMinutes();</code></td>
<td>每五分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTenMinutes();</code></td>
<td>每十分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFifteenMinutes();</code></td>
<td>每 15 分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyThirtyMinutes();</code></td>
<td>每 30 分钟运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;hourly();</code></td>
<td>每小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;hourlyAt(17);</code></td>
<td>每小时第十七分钟时执行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyOddHour($minutes = 0);</code></td>
<td>每奇数小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyTwoHours($minutes = 0);</code></td>
<td>每两小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyThreeHours($minutes = 0);</code></td>
<td>每三小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everyFourHours($minutes = 0);</code></td>
<td>每四小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;everySixHours($minutes = 0);</code></td>
<td>每六小时运行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;daily();</code></td>
<td>每天 00:00 执行一次任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;dailyAt('13:00');</code></td>
<td>每天 13：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;twiceDaily(1, 13);</code></td>
<td>每天在 1：00 和 13：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;twiceDailyAt(1, 13, 15);</code></td>
<td>每天在 1：15 和 13：15 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;weekly();</code></td>
<td>每周日00：00运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;weeklyOn(1, '8:00');</code></td>
<td>每周一 8：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;monthly();</code></td>
<td>每月第一天 00：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;monthlyOn(4, '15:00');</code></td>
<td>每月第四天 15：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;twiceMonthly(1, 16, '13:00');</code></td>
<td>每月第一天和第十六天的 13：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;lastDayOfMonth('15:00');</code></td>
<td>每月的最后一天 15：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;quarterly();</code></td>
<td>每个季度的第一天 00：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;quarterlyOn(4, '14:00');</code></td>
<td>每季度 4 日 14：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;yearly();</code></td>
<td>每年的第一天 00：00 运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;yearlyOn(6, 1, '17:00');</code></td>
<td>每年1月17日00：&lt;&gt;运行任务</td>
</tr>
<tr>
<td><code v-pre>-&gt;timezone('America/New_York');</code></td>
<td>设置任务的时区</td>
</tr>
</tbody>
</table>
<p>这些方法与额外的约束条件相结合后，可用于创建在一周的特定时间运行甚至更精细的计划任务。例如，在每周一执行命令：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// 在每周一 13:00 执行...</span></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">weekly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">mondays</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">at</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'13:00'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 在每个工作日 8:00 到 17:00 之间的每小时周期执行...</span></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'foo'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">weekdays</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">timezone</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'America/Chicago'</span><span class="token punctuation">)</span></span>
<span class="line">          <span class="token operator">-></span><span class="token function">between</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'8:00'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'17:00'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>下方列出了额外的约束条件：</p>
<table>
<thead>
<tr>
<th>方法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><code v-pre>-&gt;weekdays();</code></td>
<td>限制任务在工作日执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;weekends();</code></td>
<td>限制任务在周末执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;sundays();</code></td>
<td>限制任务在周日执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;mondays();</code></td>
<td>限制任务在周一执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;tuesdays();</code></td>
<td>限制任务在周二执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;wednesdays();</code></td>
<td>限制任务在周三执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;thursdays();</code></td>
<td>限制任务在周四执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;fridays();</code></td>
<td>限制任务在周五执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;saturdays();</code></td>
<td>限制任务在周六执行</td>
</tr>
<tr>
<td>`-&gt;days(array</td>
<td>mixed);`</td>
</tr>
<tr>
<td><code v-pre>-&gt;between($startTime, $endTime);</code></td>
<td>限制任务在 <code v-pre>$startTime</code> 和 <code v-pre>$endTime</code> 区间执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;unlessBetween($startTime, $endTime);</code></td>
<td>限制任务不在 <code v-pre>$startTime</code> 和 <code v-pre>$endTime</code> 区间执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;when(Closure);</code></td>
<td>限制任务在闭包返回为真时执行</td>
</tr>
<tr>
<td><code v-pre>-&gt;environments($env);</code></td>
<td>限制任务在特定环境中执行</td>
</tr>
</tbody>
</table>
<h4 id="周几-day-限制" tabindex="-1"><a class="header-anchor" href="#周几-day-限制"><span>周几（Day）限制</span></a></h4>
<p><code v-pre>days</code> 方法可以用于限制任务在每周的指定日期执行。举个例子，你可以在让一个命令每周日和每周三每小时执行一次：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">days</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>不仅如此，你还可以使用 <code v-pre>Illuminate\Console\Scheduling\Schedule</code> 类中的常量来设置任务在指定日期运行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Console<span class="token punctuation">\</span>Scheduling<span class="token punctuation">\</span>Schedule</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">days</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token constant">SUNDAY</span><span class="token punctuation">,</span> <span class="token class-name static-context">Schedule</span><span class="token operator">::</span><span class="token constant">WEDNESDAY</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="时间范围限制" tabindex="-1"><a class="header-anchor" href="#时间范围限制"><span>时间范围限制</span></a></h4>
<p><code v-pre>between</code> 方法可用于限制任务在一天中的某个时间段执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">between</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'7:00'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'22:00'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>同样， <code v-pre>unlessBetween</code> 方法也可用于限制任务不在一天中的某个时间段执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">hourly</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                    <span class="token operator">-></span><span class="token function">unlessBetween</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'23:00'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'4:00'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="真值检测限制" tabindex="-1"><a class="header-anchor" href="#真值检测限制"><span>真值检测限制</span></a></h4>
<p><code v-pre>when</code> 方法可根据闭包返回结果来执行任务。换言之，若给定的闭包返回 <code v-pre>true</code>，若无其他限制条件阻止，任务就会一直执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">when</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token constant boolean">true</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>skip</code> 可看作是 <code v-pre>when</code> 的逆方法。若 <code v-pre>skip</code> 方法返回 <code v-pre>true</code>，任务将不会执行：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">skip</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token constant boolean">true</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当链式调用 <code v-pre>when</code> 方法时，仅当所有 <code v-pre>when</code> 都返回 <code v-pre>true</code> 时，任务才会执行。</p>
<h4 id="环境限制" tabindex="-1"><a class="header-anchor" href="#环境限制"><span>环境限制</span></a></h4>
<p><code v-pre>environments</code> 方法可限制任务在指定环境中执行（由 <code v-pre>APP_ENV</code> <a href="https://learnku.com/docs/laravel/10.x/configurationmd#environment-configuration" target="_blank" rel="noopener noreferrer">环境变量</a> 定义）：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">environments</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'staging'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'production'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="时区" tabindex="-1"><a class="header-anchor" href="#时区"><span>时区</span></a></h3>
<p><code v-pre>timezone</code> 方法可指定在某一时区的时间执行计划任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'report:generate'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">timezone</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'America/New_York'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">at</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'2:00'</span><span class="token punctuation">)</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>若想给所有计划任务分配相同的时区，那么需要在 <code v-pre>app/Console/Kernel.php</code> 类中定义 <code v-pre>scheduleTimezone</code> 方法。该方法会返回一个默认时区，最终分配给所有计划任务：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">DateTimeZone</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取计划事件默认使用的时区</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">scheduleTimezone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name">DateTimeZone</span><span class="token operator">|</span><span class="token keyword type-declaration">string</span><span class="token operator">|</span><span class="token keyword type-declaration">null</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token string single-quoted-string">'America/Chicago'</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
请记住，有些时区会使用夏令时。当夏令时发生调整时，你的任务可能会执行两次，甚至根本不会执行。因此，我们建议尽可能避免使用时区来安排计划任务。</p>
</blockquote>
<h3 id="避免任务重复" tabindex="-1"><a class="header-anchor" href="#避免任务重复"><span>避免任务重复</span></a></h3>
<p>默认情况下，即使之前的任务实例还在执行，调度内的任务也会执行。为避免这种情况的发生，你可以使用 <code v-pre>withoutOverlapping</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">withoutOverlapping</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>在此例中，若 <code v-pre>emails:send</code> <a href="https://learnku.com/docs/laravel/10.x/artisan" target="_blank" rel="noopener noreferrer">Artisan 命令</a> 还未运行，那它将会每分钟执行一次。如果你的任务执行时间非常不确定，导致你无法准确预测任务的执行时间，那 <code v-pre>withoutOverlapping</code> 方法会特别有用。</p>
<p>如有需要，你可以在 <code v-pre>withoutOverlapping</code> 锁过期之前，指定它的过期分钟数。默认情况下，这个锁会在 24 小时后过期：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">withoutOverlapping</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>上面这种场景中，<code v-pre>withoutOverlapping</code> 方法使用应用程序的 <a href="https://learnku.com/docs/laravel/10.x/cache" target="_blank" rel="noopener noreferrer">缓存</a> 获取锁。如有必要，可以使用<code v-pre>schedule:clear cache</code> Artisan命令清除这些缓存锁。这通常只有在任务由于意外的服务器问题而卡住时才需要。</p>
<h3 id="任务只运行在一台服务器上" tabindex="-1"><a class="header-anchor" href="#任务只运行在一台服务器上"><span>任务只运行在一台服务器上</span></a></h3>
<blockquote>
<p><strong>注意</strong><br>
要使用此功能，你的应用程序必须使用 <code v-pre>database</code>, <code v-pre>memcached</code>, <code v-pre>dynamodb</code>, 或 <code v-pre>redis</code> 缓存驱动程序作为应用程序的默认缓存驱动程序。此外，所有服务器必须和同一个中央缓存服务器通信。</p>
</blockquote>
<p>如果你的应用运行在多台服务器上，可能需要限制调度任务只在某台服务器上运行。 例如，假设你有一个每个星期五晚上生成新报告的调度任务，如果任务调度器运行在三台服务器上，调度任务会在三台服务器上运行并且生成三次报告，不够优雅！</p>
<p>要指示任务应仅在一台服务器上运行，请在定义计划任务时使用 <code v-pre>onOneServer</code> 方法。第一台获取到该任务的服务器会给任务上一把原子锁以阻止其他服务器同时运行该任务:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'report:generate'</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">fridays</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">at</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'17:00'</span><span class="token punctuation">)</span></span>
<span class="line">                <span class="token operator">-></span><span class="token function">onOneServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="命名单服务器作业" tabindex="-1"><a class="header-anchor" href="#命名单服务器作业"><span>命名单服务器作业</span></a></h4>
<p>有时，你可能需要使用不同的参数调度相同的作业，同时使其仍然在单个服务器上运行作业。为此，你可以使用 <code v-pre>name</code> 方法为每个作业定义一个唯一的名字：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">job</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">CheckUptime</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'https://laravel.com'</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">name</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'check_uptime:laravel.com'</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">everyFiveMinutes</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">onOneServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">job</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">CheckUptime</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'https://vapor.laravel.com'</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">name</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'check_uptime:vapor.laravel.com'</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">everyFiveMinutes</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">            <span class="token operator">-></span><span class="token function">onOneServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你使用闭包来定义单服务器作业，则必须为他们定义一个名字</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">fn</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token class-name static-context">User</span><span class="token operator">::</span><span class="token function">resetApiRequestCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">name</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'reset-api-request-count'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token operator">-></span><span class="token function">onOneServer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="后台任务" tabindex="-1"><a class="header-anchor" href="#后台任务"><span>后台任务</span></a></h3>
<p>默认情况下，同时运行多个任务将根据它们在 <code v-pre>schedule</code> 方法中定义的顺序执行。如果你有一些长时间运行的任务，将会导致后续任务比预期时间更晚启动。 如果你想在后台运行任务，以便它们可以同时运行，则可以使用 <code v-pre>runInBackground</code> 方法:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'analytics:report'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">runInBackground</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
<code v-pre>runInBackground</code> 方法只有在通过 <code v-pre>command</code> 和 <code v-pre>exec</code> 方法调度任务时才可以使用</p>
</blockquote>
<h3 id="维护模式" tabindex="-1"><a class="header-anchor" href="#维护模式"><span>维护模式</span></a></h3>
<p>当应用处于 <a href="https://learnku.com/docs/laravel/10.x/configurationmd#maintenance-mode" target="_blank" rel="noopener noreferrer">维护模式</a> 时，Laravel 的队列任务将不会运行。因为我们不想调度任务干扰到服务器上可能还未完成的维护项目。不过，如果你想强制任务在维护模式下运行，你可以使用 <code v-pre>evenInMaintenanceMode</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">evenInMaintenanceMode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="运行调度程序" tabindex="-1"><a class="header-anchor" href="#运行调度程序"><span>运行调度程序</span></a></h2>
<p>现在，我们已经学会了如何定义计划任务，接下来让我们讨论如何真正在服务器上运行它们。<code v-pre>schedule:run</code> Artisan 命令将评估你的所有计划任务，并根据服务器的当前时间决定它们是否运行。</p>
<p>因此，当使用 Laravel 的调度程序时，我们只需要向服务器添加一个 cron 配置项，该项每分钟运行一次 <code v-pre>schedule:run</code> 命令。如果你不知道如何向服务器添加 cron 配置项，请考虑使用 <a href="https://forge.laravel.com/" target="_blank" rel="noopener noreferrer">Laravel Forge</a> 之类的服务来为你管理 cron 配置项：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">* * * * * <span class="token builtin class-name">cd</span> /path-to-your-project <span class="token operator">&amp;&amp;</span> php artisan schedule:run <span class="token operator">>></span> /dev/null <span class="token operator"><span class="token file-descriptor important">2</span>></span><span class="token file-descriptor important">&amp;1</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="本地运行调度程序" tabindex="-1"><a class="header-anchor" href="#本地运行调度程序"><span>本地运行调度程序</span></a></h3>
<p>通常，你不会直接将 cron 配置项添加到本地开发计算机。你反而可以使用 <code v-pre>schedule:work</code> Artisan 命令。该命令将在前台运行，并每分钟调用一次调度程序，直到你终止该命令为止：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan schedule:work</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="任务输出" tabindex="-1"><a class="header-anchor" href="#任务输出"><span>任务输出</span></a></h2>
<p>Laravel 调度器提供了一些简便方法来处理调度任务生成的输出。首先，你可以使用 <code v-pre>sendOutputTo</code> 方法将输出发送到文件中以便后续检查：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">sendOutputTo</span><span class="token punctuation">(</span><span class="token variable">$filePath</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果希望将输出追加到指定文件，可使用 <code v-pre>appendOutputTo</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">appendOutputTo</span><span class="token punctuation">(</span><span class="token variable">$filePath</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code v-pre>emailOutputTo</code> 方法，你可以将输出发送到指定邮箱。在发送邮件之前，你需要先配置 Laravel 的 <a href="https://learnku.com/docs/laravel/10.x/mail" target="_blank" rel="noopener noreferrer">邮件服务</a>:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'report:generate'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">sendOutputTo</span><span class="token punctuation">(</span><span class="token variable">$filePath</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">emailOutputTo</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'taylor@example.com'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你只想在命令执行失败时将输出发送到邮箱，可使用 <code v-pre>emailOutputOnFailure</code> 方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'report:generate'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">emailOutputOnFailure</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'taylor@example.com'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
<code v-pre>emailOutputTo</code>, <code v-pre>emailOutputOnFailure</code>, <code v-pre>sendOutputTo</code> 和 <code v-pre>appendOutputTo</code> 是 <code v-pre>command</code> 和 <code v-pre>exec</code> 独有的方法。</p>
</blockquote>
<h2 id="任务钩子" tabindex="-1"><a class="header-anchor" href="#任务钩子"><span>任务钩子</span></a></h2>
<p>使用 <code v-pre>before</code> 和 <code v-pre>after</code> 方法，你可以决定在调度任务执行前或者执行后来运行代码：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">before</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// 任务即将执行。。。</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">after</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// 任务已经执行。。。</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 <code v-pre>onSuccess</code> 和 <code v-pre>onFailure</code> 方法，你可以决定在调度任务成功或者失败运行代码。失败表示 Artisan 或系统命令以非零退出码终止：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">onSuccess</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// 任务执行成功。。。</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">onFailure</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// 任务执行失败。。。</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你的命令有输出，你可以使用<code v-pre>after</code>, <code v-pre>onSuccess</code> 或 <code v-pre>onFailure</code>钩子并传入类型为<code v-pre>Illuminate\Support\Stringable</code>的<code v-pre>$output</code>参数的闭包来访问任务输出：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Stringable</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">onSuccess</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Stringable</span> <span class="token variable">$output</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// The task succeeded...</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">onFailure</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">Stringable</span> <span class="token variable">$output</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">             <span class="token comment">// The task failed...</span></span>
<span class="line">         <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="pinging-网址" tabindex="-1"><a class="header-anchor" href="#pinging-网址"><span>Pinging 网址</span></a></h4>
<p>使用 <code v-pre>pingBefore</code> 和 <code v-pre>thenPing</code> 方法，你可以在任务完成之前或完成之后来 ping 指定的 URL。当前方法在通知外部服务，如 <a href="https://envoyer.io/" target="_blank" rel="noopener noreferrer">Envoyer</a>，计划任务在将要执行或已完成时会很有用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">pingBefore</span><span class="token punctuation">(</span><span class="token variable">$url</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">thenPing</span><span class="token punctuation">(</span><span class="token variable">$url</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>只有当条件为 <code v-pre>true</code> 时，才可以使用 <code v-pre>pingBeforeIf</code> 和 <code v-pre>thenPingIf</code> 方法来 ping 指定 URL ：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">pingBeforeIf</span><span class="token punctuation">(</span><span class="token variable">$condition</span><span class="token punctuation">,</span> <span class="token variable">$url</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">thenPingIf</span><span class="token punctuation">(</span><span class="token variable">$condition</span><span class="token punctuation">,</span> <span class="token variable">$url</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当任务成功或失败时，可使用 <code v-pre>pingOnSuccess</code> 和 <code v-pre>pingOnFailure</code> 方法来 ping 给定 URL。失败表示 Artisan 或系统命令以非零退出码终止：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$schedule</span><span class="token operator">-></span><span class="token function">command</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'emails:send'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">daily</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">pingOnSuccess</span><span class="token punctuation">(</span><span class="token variable">$successUrl</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">pingOnFailure</span><span class="token punctuation">(</span><span class="token variable">$failureUrl</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>所有 ping 方法都依赖 Guzzle HTTP 库。通常，Guzzle 已在所有新的 Laravel 项目中默认安装，不过，若意外将 Guzzle 删除，则可以使用 Composer 包管理器将 Guzzle 手动安装到项目中：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line"><span class="token function">composer</span> require guzzlehttp/guzzle</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="事件" tabindex="-1"><a class="header-anchor" href="#事件"><span>事件</span></a></h2>
<p>如果需要，你可以监听调度程序调度的 <a href="https://learnku.com/docs/laravel/10.x/events" target="_blank" rel="noopener noreferrer">事件</a>。通常，事件侦听器映射将在你的应用程序的 <code v-pre>App\Providers\EventServiceProvider</code> 类中定义：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 应用的事件监听器映射</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token variable">$listen</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token string single-quoted-string">'Illuminate\Console\Events\ScheduledTaskStarting'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'App\Listeners\LogScheduledTaskStarting'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'Illuminate\Console\Events\ScheduledTaskFinished'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'App\Listeners\LogScheduledTaskFinished'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'Illuminate\Console\Events\ScheduledBackgroundTaskFinished'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'App\Listeners\LogScheduledBackgroundTaskFinished'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'Illuminate\Console\Events\ScheduledTaskSkipped'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'App\Listeners\LogScheduledTaskSkipped'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"></span>
<span class="line">    <span class="token string single-quoted-string">'Illuminate\Console\Events\ScheduledTaskFailed'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'App\Listeners\LogScheduledTaskFailed'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/10.x/scheduling/14875" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/10.x/sc...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/10.x/scheduling/14875" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/10.x/sc...</a></p>
</blockquote>
</div></template>


